
#ifndef _TTG_EXTRAS_MULOPERATIONS_
#define _TTG_EXTRAS_MULOPERATIONS_
#include "Common/Definitions.h"

#include "Operations.h"

namespace ttg_internal
{
	//Implements multiplication of diffrent-type values.
	template <class T, class M, class R = T>
	class MulOperation :public ttg::extras::Operation<R>
	{
		protected:
			ttg::extras::Operation<T> *source1;
			ttg::extras::Operation<M> *source2;
		public:
			inline MulOperation(ttg::extras::Operation<T> *source1 = NULL,
								ttg::extras::Operation<M> *source2 = NULL)
			{
				this->source1 = source1;
				this->source2 = source2;
			}
			//Operation member.
			virtual R calculate()
			{
				return source1->calculate() * source2->calculate();
			}
			//Operation member.
			virtual bool isStatic()
					{ return source1->isStatic() && source2->isStatic(); }
			~MulOperation()
			{
				SAFE_DELETE(source1);
				SAFE_DELETE(source2);
			}
			//Creates operation with given sources. In case of error returns NULL.
			virtual OperationInfo *createInstance(OperationInfo *s1,
												  OperationInfo *s2,
												  OperationInfo *s3)
			{
				ttg::extras::Operation<T> *op1 = dynamic_cast<Operation<T> *>(s1);
				ttg::extras::Operation<M> *op2 = dynamic_cast<Operation<M> *>(s2);
				if (op1 == NULL || op2 == NULL)
					return NULL;
				else
				{
					return new MulOperation<T, M, R>(op1, op2);
				}
			}
	};

	ttg::math::vec3f MulOperation<ttg::math::mat4x4f, ttg::math::vec3f, ttg::math::vec3f>::calculate()
	{
		return source1->calculate().operator *((ttg::math::vec4f)source2->calculate());
	}

	ttg::math::vec3f MulOperation<float, ttg::math::vec3f, ttg::math::vec3f>::calculate()
	{
		return source2->calculate().operator *(source1->calculate());
	}
}

#endif
